<?php
class localhostCatalog extends CatalogBase
{
	const ADMIN_GROUP = "admin";

	public static $secureMode = true;

	private $token;
	private $tokenAdmin;

	public function __construct()
	{
		// No se permite más que una instancia por esquema.
		//
		if ( isset(self::$instance) ) {
			return(self::$instance);
		}

		// Se definen los datos para este esquema.
		//
		$this->name     = "Esquema Local";
		$this->username = "nereyda";
		$this->password = "Asdf123456";
		$this->catalog  = "nereyda";
		$this->server   = "localhost";
		$this->port     = "";

		self::$instance = $this;

		// Se registran los objetos de acceso a datos
		// que se utilizarán en esta conexión.
		//
		$this->DAORegister("GeneralDAO",  "base"    );
		$this->DAORegister("SecureDAO",   "secure"  );
		$this->DAORegister("UsersDAO",    "users"   );
		$this->DAORegister("ServicesDAO", "services");
		$this->DAORegister("AdminDAO",    "admin"   );
		$this->DAORegister("CalendarDAO", "calendar");

		// Crea los token para validar las consultas SQL.
		//
		$this->token = new Token($this, true);
		$this->tokenAdmin = new Token($this, true);

		$this->token->bind( "validateSessionWrapper", Token::METHOD );
		$this->tokenAdmin->bind( "validateAdminWrapper", Token::METHOD );
	}

	/**
	 * Se desencadena cuando la conexión a la base
	 * de datos ya se ha establecido y preparado.
	 */
	protected function onConnect()
	{
		$this->createUserQueries();
		$this->createServicesQueries();
		$this->createAdminQueries();
		$this->createCalendarQueries();
	}

	/**
	 * Función vinculada a un token de seguridad.
	 * Será llamada antes de ejecutarse cualquier
	 * consulta SQL a la base de datos. Si devuelve
	 * true, la consulta se realizará, en caso de
	 * retornar false, se evitará la ejecución.
	 */
	public function validateSessionWrapper()
	{
		$success = Auth::getInstance()->validateSession();

		if ( !$success ) {
			Services::invoke("LogOut", Session::$context, true);
		}

		return($success);
	}

	public function validateAdminWrapper()
	{
		$data     = base64_decode( Session::$context->passwd() );
		$passwd   = Crypto::decrypt( $data, Session::$sid );
		$username = Session::$context->username();

		$user = $this->users->exists( $username, $passwd );

		if ( !$user || ($user->group != self::ADMIN_GROUP))
			return( false );

		return( true );
	}

	/**
	 * Registra las consultas SQL correspondientes a
	 * la tabla de usuarios.
	 */
	private function createUserQueries()
	{
		$token      = $this->token;
		$tokenAdmin = $this->tokenAdmin;

		// Registra las tablas a las que podrá acceder este DAO.
		//
		$this->tableRegister($this->users, "User"  );
		$this->tableRegister($this->users, "Group" );

		$this->createQuery($this->users, "getGroups",
			"CALL getGroups();"
		);

		$this->createQuery($this->users, "getGroupUsersById",
			"CALL getGroupUsersById(:1);"
		);

		$this->createQuery($this->users, "getGroupUsersByName",
			"CALL getGroupUsersByName(:1);"
		);

		$this->createQuery($this->users, "getGroupUsersByRol",
			"CALL getGroupUsersByRol(:1);"
		);

		$this->createQuery($this->users, "getUserById",
			"CALL getUserById(:1, :2);"
		);

		$this->createQuery($this->users, "userAuthenticate",
			"CALL userAuthenticate(:1, :2);"
		);

		$this->createQuery($this->users, "getUserGroup",
			"CALL getUserGroup(:1, :2);"
		);

		$this->createQuery($this->users, "getUserProfile",
			"CALL getUserProfile(:1, :2);"
		);

		$this->createQuery($this->users, "getUserContacts",
			"CALL getUserContacts(:1, :2);"
		);

		$this->createQuery($token, $this->users, "getUserSevices",
			"CALL getUserSevices(:1,:2);"
		);

		$this->createQuery($this->users, "getUserKey",
			"CALL getUserKey(:1,:2);"
		);

		$this->createQuery($token, $this->users, "saveUser",
			"CALL saveUser(:1,:2,:3,:4,:5);"
		);

		$this->createQuery($this->users, "saveProfile",
			"CALL saveProfile(:1,:2,:3,:4,:5,:6,:7,:8,:9);"
		);
	}

	/**
	 * Registra las consultas SQL correspondientes
	 * a la tabla de servicios.
	 */
	private function createServicesQueries()
	{
		$token      = $this->token;
		$tokenAdmin = $this->tokenAdmin;

		// Registra las tablas a las que podrá acceder este DAO.
		//
		$this->tableRegister($this->services, "UserServiceJoin");
		$this->tableRegister($this->services, "Service"        );

		$this->createQuery($this->services, "svcEnumPublic",
			"SELECT * FROM services WHERE attribs=2"
		);

		$this->createSecureQuery($token, $this->services, "svcEnumShared",
			"SELECT * FROM services WHERE attribs=4"
		);

		$this->createSecureQuery($token, $this->services, "svcEnumPrivate",
			"SELECT * FROM services WHERE attribs=8"
		);

		$this->createSecureQuery($tokenAdmin, $this->services, "svcEnumRoot",
			"SELECT * FROM services WHERE attribs=256"
		);

		$this->createSecureQuery($token, $this->services, "getUserServices",
			"SELECT user.uid, svc.servName AS service
			 FROM   users_services AS user
			 INNER JOIN services AS svc
			 ON svc.id=user.sid
			 WHERE user.uid=:1"
		);

		$this->createSecureQuery($token, $this->services, "svcEnumShared",
			"SELECT servName AS service
			 FROM services
			 WHERE attribs=4"
		);

		$this->createSecureQuery($token, $this->services, "serviceExists",
			"SELECT COUNT(*) FROM services WHERE servName=:1"
		);
	}

	/**
	 * Registra las consultas SQL correspondientes
	 * a la administración del sistema.
	 */
	private function createAdminQueries()
	{
		$token      = $this->token;
		$tokenAdmin = $this->tokenAdmin;

		// Registra las tablas a las que podrá acceder este DAO.
		//
		$this->tableRegister($this->admin, "User"    );
		$this->tableRegister($this->admin, "Group"   );
		$this->tableRegister($this->admin, "Service" );
		$this->tableRegister($this->admin, "UserServiceJoin" );

		$this->createSecureQuery($tokenAdmin, $this->admin, "enumUsers",
			"SELECT * FROM users ORDER BY username"
		);

		$this->createSecureQuery($tokenAdmin, $this->admin, "enumGroups",
			"SELECT * FROM groups ORDER BY grpname"
		);

		$this->createSecureQuery($tokenAdmin, $this->admin, "enumUserServices",
			"SELECT * FROM users ORDER BY username"
		);

		$this->createSecureQuery($tokenAdmin, $this->admin, "adminGetUser",
			"SELECT * FROM users WHERE username=:1 LIMIT 1"
		);
	}

	/**
	 * Registra las consultas SQL correspondientes
	 * a la administración del sistema.
	 */
	private function createCalendarQueries()
	{
		$token      = $this->token;
		$tokenAdmin = $this->tokenAdmin;

		// Registra las tablas a las que podrá acceder este DAO.
		//
		$this->tableRegister( $this->calendar, "CalendarEntrySet"     );
		$this->tableRegister( $this->calendar, "CalendarEntryFriends" );
		$this->tableRegister( $this->calendar, "CalendarEvent"        );
		$this->tableRegister( $this->calendar, "CalendarCategory"     );

		$this->createQuery( $this->calendar, "getEntriesByDate",
			"SELECT ces.id, ces.idEvent, cev.idCategory, ces.date,
			        ces.description, cev.name as 'event', cca.name as 'category'
			 FROM Calendar_EntrySet ces
			 LEFT JOIN Calendar_Event cev
			   ON ces.idEvent = cev.id
			 LEFT JOIN Calendar_Category cca
			   ON cev.idCategory = cca.id
			 WHERE ces.date=:1
			 ORDER BY ces.date
			"
		);
		$this->createQuery( $this->calendar, "getEventsByCategory",
			"
			SELECT cev.id, cev.idCategory, cev.name as 'event',
				   cca.name as 'category'
			FROM Calendar_Event cev
			LEFT JOIN Calendar_Category cca
			  ON cev.idCategory = cca.id
			WHERE cca.id=:1
			"
		);
		$this->createQuery( $this->calendar, "getCategories",
			"
			SELECT cca.id, cca.idParent, cca.name as 'category'
			FROM Calendar_Category cca
			LEFT JOIN Calendar_Category cca2
			  ON cca2.id = cca.idParent
			GROUP BY cca.id ASC
			"
		);
		$this->createQuery( $this->calendar, "createCategory",
			"
			INSERT INTO Calendar_Category VALUES (0, :1, :2)
			"
		);
		$this->createQuery( $this->calendar, "createEvent",
			"
			INSERT INTO Calendar_Event VALUES (0, :1, :2)
			"
		);
		$this->createQuery( $this->calendar, "updateCategory",
			"
			UPDATE Calendar_Category SET idParent=1, name='Trabajo2'
			WHERE id=2
			"
		);
		$this->createQuery( $this->calendar, "updateEvent",
			"
			UPDATE Calendar_Event SET idCategory=:1, name=:2
			WHERE id=:3
			"
		);
		$this->createQuery( $this->calendar, "deleteCategory",
			"
			DELETE FROM Calendar_Category WHERE id=:1
			"
		);
		$this->createQuery( $this->calendar, "deleteEvent",
			"
			DELETE FROM Calendar_Event WHERE id=:1
			"
		);
	}

	/**
	 * Registra las consultas SQL correspondientes
	 * a la administración del sistema.
	 */
	private function createDocumentsQueries()
	{
		$token      = $this->token;
		$tokenAdmin = $this->tokenAdmin;

		// Registra las tablas a las que podrá acceder este DAO.
		//
		$this->tableRegister( $this->documents, "CalendarEntrySet"     );
		$this->tableRegister( $this->documents, "CalendarEntryFriends" );
		$this->tableRegister( $this->documents, "CalendarEvent"        );
		$this->tableRegister( $this->documents, "CalendarCategory"     );

		$this->createQuery( $this->documents, "getMasterTable",
			"
			SELECT inode.inode, fentry.idEntry AS fentry,
				   dentry.idDirectory AS dentry,
				   dentry.idParent AS dentry_parent,
				   inode.srv_filename AS remoteFile,
				   fentry.filename AS virtualFile,
				   dentry.name AS virtualDir,
				   fentry.use_count AS useCount
			FROM pfs_entry entry
			LEFT JOIN pfs_inode inode
			  ON entry.inode = inode.inode
			LEFT JOIN pfs_fentry fentry
			  ON fentry.idEntry = entry.fentry
			LEFT JOIN pfs_dentry dentry
			  ON dentry.idDirectory = entry.dentry
			GROUP BY inode.inode
			"
		);

		$this->createQuery( $this->documents, "queryDirectory",
			"
			SELECT inode.inode, fentry.idEntry AS fentry,
				   dentry.idDirectory AS dentry,
				   inode.srv_filename AS remoteFile,
				   fentry.filename AS virtualFile,
				   dentry.name AS virtualDir,
				   fentry.use_count AS useCount
			FROM pfs_entry entry
			LEFT JOIN pfs_inode inode
			  ON entry.inode = inode.inode
			LEFT JOIN pfs_fentry fentry
			  ON fentry.idEntry = entry.fentry
			LEFT JOIN pfs_dentry dentry
			  ON dentry.idDirectory = entry.dentry
			WHERE entry.dentry=:1
			GROUP BY inode.inode
			"
		);

		$this->createQuery( $this->documents, "getSubdirectories",
			"
			SELECT inode.inode, fentry.idEntry AS fentry,
				   dentry.idDirectory AS dentry,
				   inode.srv_filename AS remoteFile,
				   fentry.filename AS virtualFile,
				   dentry.name AS virtualDir,
				   fentry.use_count AS useCount
			FROM pfs_entry entry
			LEFT JOIN pfs_inode inode
			  ON entry.inode = inode.inode
			LEFT JOIN pfs_fentry fentry
			  ON fentry.idEntry = entry.fentry
			LEFT JOIN pfs_dentry dentry
			  ON dentry.idDirectory = entry.dentry
			WHERE entry.dentry=:1
			GROUP BY inode.inode
			"
		);
	}
}
?>
